package com.aries.rpc.spring.starter.client.helper;

import com.aries.dubbo.like.rpc.client.proxy.ServiceProxy;
import com.aries.dubbo.like.rpc.common.annotations.EnableRpcConsumer;
import com.aries.dubbo.like.rpc.common.annotations.RpcConsumer;
import com.aries.dubbo.like.rpc.common.annotations.RpcProvider;
import com.aries.dubbo.like.rpc.common.util.ClassUtil;
import com.aries.dubbo.like.rpc.service.util.discover.zk.ZookeeperInstance;
import com.aries.rpc.spring.starter.config.RpcConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Field;

/**
 * Created with IntelliJ IDEA.
 * Author: aries
 * Date: 2018/8/23
 * Description:  将bean中被rpcConsumer注释的field 赋值为动态代理生成的proxy
 */
@Configuration
@Slf4j
@ConditionalOnClass({RpcConsumer.class})
@EnableConfigurationProperties(RpcConfiguration.class)
public class RpcClientConfiguration {
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private RpcConfiguration rpcConfiguration;

    @Bean
    public BeanPostProcessor beanPostProcessor() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                //设置class util的basePackage
                ClassUtil.setBasePath(rpcConfiguration.getBasePath());
                Class<?> clz = bean.getClass();
                for (Field field : clz.getDeclaredFields()) {
                    if (field.isAnnotationPresent(RpcConsumer.class)) {
                        log.info("set annotated with @RpcConsumer filed: " + field.getName());
                        try {
                            RpcConsumer rpcConsumer = field.getDeclaredAnnotation(RpcConsumer.class);
                            Class<?> interfaceClass;
                            if (rpcConsumer.interfaceClass() != Void.class) {
                                interfaceClass = rpcConsumer.interfaceClass();
                            } else {
                                interfaceClass = field.getType();
                            }
                            field.setAccessible(true);
                            field.set(bean, ServiceProxy.newInstance(interfaceClass));
                        } catch (IllegalAccessException e) {
                            log.error("set field " + clz.getName() + "." + field.getName() + "error", e);
                            throw new RuntimeException("set field error", e);
                        }
                    }

//                    if (field.isAnnotationPresent(Autowired.class) && clz.isAnnotationPresent(RpcProvider.class)) {
//                        if (field.getType().getInterfaces().length > 0) {
//                            try {
//                                field.set(bean, applicationContext.getBean(field.getClass().getInterfaces()[0]));
//                                log.info("set field:" + field.getName() + " values:" + applicationContext.getBean(field.getClass().getInterfaces()[0].getClass()).getName());
//                            } catch (IllegalAccessException e) {
//                                log.error("set field " + field.getName() + " annotated with Autowird in class with RpcProvider failed.(interface injected)");
//                            }
//                        } else {
//                            try {
//                                field.set(bean, applicationContext.getBean(field.getType().getClass()));
//                                log.info("set field:" + field.getName() + " values:" + applicationContext.getBean(field.getType().getClass()).getName());
//                            } catch (IllegalAccessException e) {
//                                log.error("set field " + field.getName() + " annotated with Autowird in class with RpcProvider failed.(constructor injected)");
//                            }
//                        }
//
//                    }
                }
//
//                Arrays.stream(clz.getFields()).forEach(field -> {
//                    if (field.isAnnotationPresent(RpcConsumer.class)) {
//                        System.out.println("------------------------------------------------------------------");
//                        Class<?> interfaceClz = field.getDeclaredAnnotation(RpcConsumer.class).interfaceClass();
//                        try {
//                            System.out.println("try to set field");
//                            field.set(bean, ServiceProxy.newInstance(interfaceClz));
//                        } catch (IllegalAccessException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                });

                return bean;
            }
        };
    }


}
